


#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "qelib.h"



#define SHELL_LOGNAME      "shelltask"
#define shell_debug(...)   qelog_debug(SHELL_LOGNAME,   __VA_ARGS__)
#define shell_info(...)    qelog_info(SHELL_LOGNAME,    __VA_ARGS__)
#define shell_notice(...)  qelog_notice(SHELL_LOGNAME,  __VA_ARGS__)
#define shell_warning(...) qelog_warning(SHELL_LOGNAME, __VA_ARGS__)
#define shell_error(...)   qelog_error(SHELL_LOGNAME,   __VA_ARGS__)
#define shell_fatal(...)   qelog_fatal(SHELL_LOGNAME,   __VA_ARGS__)
#define shell_hexdump(...) qehex_debug(SHELL_LOGNAME,   __VA_ARGS__)



static qe_shell shell;
static QueueHandle_t rx_msgq;
static qe_dev *uartdev;
static int rx_indicate_size = 0;

static void shell_log_output(const char *message)
{
    qe_shell_write_end_line(&shell, (char *)message, qe_strlen(message));
}

// const struct qe_shell_command command_tab[] = {

//    QE_SHELL_USR_ITEM(QE_SHELL_DEFAULT_USER, QE_SHELL_DEFAULT_PSWD, default user),

//    QE_SHELL_KEY_ITEM(0x1B5B4100,  qe_shell_key_up,     up),
//    QE_SHELL_KEY_ITEM(0x1B5B4200,  qe_shell_key_down,   down),
//    QE_SHELL_KEY_ITEM(0x1B5B4300,  qe_shell_key_right,  right),
//    QE_SHELL_KEY_ITEM(0x1B5B4400,  qe_shell_key_left,   left),
//    QE_SHELL_KEY_ITEM(0x0D000000,  qe_shell_key_enter,  enter),
//    QE_SHELL_KEY_ITEM(0x08000000,  qe_shell_key_backspace,  backspace),
//    QE_SHELL_CMD_EXEC(help,        qe_shell_cmd_help,   show help info),
//    QE_SHELL_CMD_FUNC(2, setvar,   qe_shell_cmd_setvar, set variable),
//    QE_SHELL_CMD_FUNC(1, getvar,   qe_shell_cmd_getvar, set variable),

//    QE_SHELL_VAR_INT(test_num,     &var_test_num, shell test num),
//    QE_SHELL_VAR_STR(test_str,     var_test_str,  shell test str),
// };

static qe_ret rx_indicate(struct qe_device *dev, qe_size size)
{
    char event;
    BaseType_t woken = pdFALSE;
    qe_assert(rx_msgq);
    rx_indicate_size = size;
    xQueueSendFromISR(rx_msgq, &event, &woken);
    portYIELD_FROM_ISR(woken);
    return qe_ok;
}

int shell_read(char *data, int len)
{
    int n = 0;
    char event;
    if (!rx_msgq) {
        shell_error("rx msgq error");
        return -1;
    }

    if (pdPASS == xQueueReceive(rx_msgq, &event, portMAX_DELAY)) {
        int n = qe_dev_read(uartdev, 0, data, len);
        // if (n > 0)
        //     shell_debug("read 0x%x", *data);
        return n;
    }
    
    return n;
}

int shell_write(char *data, int len)
{
    int n = qe_dev_write(uartdev, 0, data, len);
    return n;
}

static void shell_task(void *args)
{
	char data;
    shell_debug("shell_launch");
    qe_memset(&shell, 0x0, sizeof(shell));
    rx_msgq = xQueueCreate(8, sizeof(char));
    qe_assert(rx_msgq);

    uartdev = qe_dev_find("uart1");
    qe_assert(uartdev != QE_NULL);
    shell_debug("find uart %p", uartdev);
    qe_dev_set_rx_indicate(uartdev, rx_indicate);
    shell_debug("set rx indicate");
    qe_dev_open(uartdev, QE_DEV_F_INT_RX);
    shell_debug("uart open");
    qe_shell_init(&shell, 4096,
    		QE_SHELL_DEFAULT_USER, shell_read, shell_write);
    qelog_set_default_output(shell_log_output);
    shell_debug("shell init");

    //fymodem_set_callback(ymodem_getc, ymodem_putc, ymodem_flush);

    while (1) {
        if (shell.read && shell.read(&data, 1) == 1) {
            qe_shell_handler(&shell, data);
        }
    }
}

static qe_unused qe_init int shell_launch(void)
{
    xTaskCreate(shell_task, "shell", 0x4096, QE_NULL, 3, QE_NULL);
    return 0;
}
QE_APP_EXPORT(shell_launch);
